package org.example3;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.Modifier;

/**
 *  修改PersonService类信息,并调用修改后的方法
 */
public class AppModifyExistClassBySsist {

    public static void main(String[] args) throws Exception{

//        invokeBeforeModify();

        Class modifiedClazz = modifyExistingClass();

        System.out.println();
        // 5.实例化目标类
        Object personService = modifiedClazz.newInstance();
        // 调用无参无返回值fly方法
        modifiedClazz.getMethod("fly").invoke(personService);

        System.out.println();
        // 调用有参有返回值的say方法
        Object returnVal = modifiedClazz.getMethod("say", new Class[]{String.class}).invoke(personService, "我是时春跃");
        System.out.println(returnVal);
    }

    public static void invokeBeforeModify() throws Exception{
        Class<?> aClass = Class.forName("org.example3.PersonService");

        Object o = aClass.newInstance();
        aClass.getDeclaredMethod("fly").invoke(o);

    }

    public static Class modifyExistingClass() throws Exception {
        String postFix = "target/modifiedClazz";
        String genDir = System.getProperty("user.dir")+"/javassistTest/" +postFix ;

        System.out.println("更新后的class文件,放在"+postFix);

        // 1.创建classPool，使用的是默认系统的类搜索路径。
        ClassPool classPool = ClassPool.getDefault();

        // 2.获取要修改的class
        CtClass ctClass = classPool.get("org.example3.PersonService");

        // 3.获取目标类的方法
        CtMethod fly = ctClass.getDeclaredMethod("fly");
        // 在方法执行前插入代码
        fly.insertBefore("System.out.println(\"fly方法执行---前\");");
        // 在方法执行后插入代码
        fly.insertAfter("System.out.println(\"fly方法执行---后\");");

        // 4.新增一个方法
        //添加带入参和返回值的方法say
        CtMethod sayMethod = new CtMethod(classPool.getCtClass("java.lang.String"), "say",
                new CtClass[]{classPool.getCtClass("java.lang.String")}, ctClass);
        sayMethod.setModifiers(Modifier.PUBLIC);
        StringBuilder builder = new StringBuilder();
        builder.append("{\nSystem.out.println(\"PersonService类的say方法执行了\");\n");
        builder.append("return \"返回值是:\" + $1 ; \n}");
        sayMethod.setBody(builder.toString());
        ctClass.addMethod(sayMethod);

        ctClass.writeFile(genDir);

        return ctClass.toClass();

    }
}
